package sf.r2dbc.sql;

import io.r2dbc.spi.Connection;
import io.r2dbc.spi.ConnectionFactory;
import sf.database.dao.DBContext;
import sf.database.dialect.DBDialect;
import sf.database.dialect.DialectUtils;
import sf.r2dbc.binding.BindMarker;
import sf.r2dbc.binding.BindMarkers;
import sf.r2dbc.binding.BindMarkersFactory;
import sf.r2dbc.binding.BuiltInBindMarkersFactoryUtils;
import sf.r2dbc.connection.R2dbcConnection;

import java.util.List;

public class R2dbcUtils {

    public static DBDialect getDBDialect(ConnectionFactory connectionFactory) {
        return DialectUtils.getDialect(connectionFactory.getMetadata().getName(), null);
    }

    public static DBDialect getDBDialect(Connection connection) {
        if (connection instanceof R2dbcConnection) {
            R2dbcConnection r2dbcConnection = (R2dbcConnection) connection;
            if (r2dbcConnection.getDbDialect() != null) {
                return r2dbcConnection.getDbDialect();
            }
            if (r2dbcConnection.getConnectionFactory() != null) {
                return getDBDialect(r2dbcConnection.getConnectionFactory());
            }
        }
        return DialectUtils.getDialect(connection.getMetadata().getDatabaseProductName(), connection.getMetadata().getDatabaseVersion());
    }

    public static BindMarkersFactory getBindMarkersFactory(Connection connection) {
        if (connection instanceof R2dbcConnection) {
            R2dbcConnection r2dbcConnection = (R2dbcConnection) connection;
            if (r2dbcConnection.getR2dbcContext() != null &&
                    r2dbcConnection.getR2dbcContext().getBindMarkersFactory() != null) {
                return r2dbcConnection.getR2dbcContext().getBindMarkersFactory();
            }
            if (r2dbcConnection.getConnectionFactory() != null) {
                return BuiltInBindMarkersFactoryUtils.getBindMarkers(r2dbcConnection.getConnectionFactory());
            }
        }
        return BuiltInBindMarkersFactoryUtils.getBindMarkers(connection);
    }

    public static DBContext getDBContext(Connection connection) {
        if (connection instanceof R2dbcConnection) {
            R2dbcConnection r2dbcConnection = (R2dbcConnection) connection;
            return r2dbcConnection.getDbContext();
        }
        return null;
    }

    public static Boolean getAutoCommit(Connection connection) {
        if (connection == null) {
            return null;
        }
        return connection.isAutoCommit();
    }

    /**
     * 该方法主要是提供将jdbc sql转换为r2dbc sql的功能
     * @param bmf  spring r2dbc提供的绑定工厂
     * @param list 绑定列表
     * @param sql  jdbc的sql
     * @return 转换后的sql
     */
    public static String parseSql(BindMarkersFactory bmf, List<BindMarker> list, String sql) {
        BindMarkers bms = bmf.create();
        StringBuilder sb = new StringBuilder(sql.length());
        for (int i = 0; i < sql.length(); i++) {
            char c = sql.charAt(i);
            if (c == '?') {//如果字段带?怎么办
                BindMarker bm = bms.next();
                list.add(bm);
                sb.append(bm.getPlaceholder());
            } else {
                sb.append(c);
            }
        }
//        if (bmf.identifiablePlaceholders()) {
//            //bindName
//        } else {
//            //bindIndex
//        }
        return sb.toString();
    }
}
